package cn.nexd.location.indoor.core.mathematician;


import android.util.Log;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import cn.nexd.location.indoor.bean.IndoorLocationData;
import de.bwaldvogel.liblinear.Feature;
import de.bwaldvogel.liblinear.FeatureNode;
import de.bwaldvogel.liblinear.Linear;
import de.bwaldvogel.liblinear.Model;


public class Detection {

    private static final Map<String, String> floorMap = new HashMap<String, String>();

    static InputStream readmeReader = null;
    static InputStream modelReader = null;
    static BufferedReader bufferedReader;
    private static long buildingId = -1L;

    public static void free() {
        buildingId = -1L;
    }

    public static void setCurrentBuildingId(long buildingId) {
        Detection.buildingId = buildingId;
    }

    public static long getCurrentBuildingId() {
        return buildingId;
    }


    //    public static void setLocationConfig(Context context, String mallId) {
    //        try {
    //            readmeReader = context.getAssets().open(mallId + "/README.CONF");
    //            bufferedReader = new BufferedReader(new InputStreamReader(readmeReader));
    //            StringBuffer stringBuffer = new StringBuffer();
    //            String content;
    //            // 一次读入一行，直到读入null为文件结束
    //            while ((content = bufferedReader.readLine()) != null) {
    //                stringBuffer.append(content);
    //                stringBuffer.append("\n");
    //            }
    //
    //            String[] split = stringBuffer.toString().split("\\n");
    //
    //            floorMap.clear();
    //
    //            for (int i = 0; i < split.length; i++) {
    //                String[] floor = split[i].split(":");
    //                floorMap.put(floor[0], floor[1]);
    //            }
    //
    //
    //            modelReader = context.getAssets().open(mallId + "/model");
    //            model = Model.load(new InputStreamReader(modelReader));
    //
    //            wifiListReader = new BufferedReader(new InputStreamReader(context.getAssets().open(mallId + "/wifilist.txt")));
    //
    //            String line = wifiListReader.readLine();
    //            names = line.split(",");
    //            wifiListReader.close();
    //
    //            if (nameList == null) {
    //                nameList = new ArrayList<String>();
    //            } else {
    //                nameList.clear();
    //            }
    //
    //            Collections.addAll(nameList, names);
    //
    //        } catch (IOException e) {
    //            e.printStackTrace();
    //        }
    //    }

    public static void setDetectionConfig(String conf, String model, String wifiList) throws IOException {
        Log.d("filepath", " " + conf + "  \n" + model + "  \n" + wifiList);
        setDetectionConfig(new FileInputStream(conf), new FileInputStream(model), new FileInputStream(wifiList));
    }

    public static void setDetectionConfig(InputStream readme, InputStream modelInputStream, InputStream wifilist) throws IOException {
        bufferedReader = new BufferedReader(new InputStreamReader(readme));

        StringBuffer stringBuffer = new StringBuffer();
        String content;
        // 一次读入一行，直到读入null为文件结束
        while ((content = bufferedReader.readLine()) != null) {
            stringBuffer.append(content);
            stringBuffer.append("\n");
        }

        String[] split = stringBuffer.toString().split("\\n");

        floorMap.clear();

        for (int i = 0; i < split.length; i++) {
            String[] floor = split[i].split(":");
            floorMap.put(floor[0], floor[1]);
        }


        //
        model = Model.load(new InputStreamReader(modelInputStream));

        wifiListReader = new BufferedReader(new InputStreamReader(wifilist));

        String line = wifiListReader.readLine();
        names = line.split(",");
        wifiListReader.close();

        if (nameList == null) {
            nameList = new ArrayList<String>();
        } else {
            nameList.clear();
        }

        Collections.addAll(nameList, names);
    }


    public static String getLocationFloorId(Map<String, Double> wiFiData) {
        String floorPath = "";
        try {
            int floorId = (int) getFloorId(wiFiData);

            floorPath = floorMap.get(String.valueOf(floorId));

        } catch (IOException e) {
            e.printStackTrace();
        }

        return floorPath;
    }

    public static long getLocationFloorId(List<IndoorLocationData> indoorLocationDatas) {
        return Long.parseLong(getLocationFloorId(getMap(indoorLocationDatas)));
    }

    private static Map<String, Double> getMap(List<IndoorLocationData> indoorLocationDatas) {
        Map<String, Double> map = new HashMap<>();
        for (IndoorLocationData indoorLocationData : indoorLocationDatas) {
            map.put(indoorLocationData.getMac(), parseWifiSign(indoorLocationData.getLevel()));
        }
        return map;
    }

    private static double parseWifiSign(double wifiSign) {
        double parseWifiSing = wifiSign + 100d;
        if (parseWifiSing < 20) {
            parseWifiSing = 0.0d;
        }
        return parseWifiSing;
    }

    static Model model = null;

    private static double getFloorId(Map<String, Double> wiFiData) throws IOException {
        Feature[] testNode = getFeature(wiFiData);
        double prediction = Linear.predict(model, testNode);
        return prediction;
    }

    private static Feature[] getFeature(Map<String, Double> wiFiData) throws IOException {
        Map<Integer, Double> indexedWiFiData = new HashMap<Integer, Double>();
        List<String> nameIndex = getNameList();
        //        Double maxValue = 0.0;
        //        for (String s : wiFiData.keySet()) {
        //            int ind = nameIndex.indexOf(s);
        //            double wv = wiFiData.get(s);
        //            if (ind >= 0 && maxValue < wv) {
        //                maxValue = wiFiData.get(s);
        //            }
        //        }
        //
        //        for (String s : wiFiData.keySet()) {
        //            int ind = nameIndex.indexOf(s);
        //            if (ind >= 0) {
        //                indexedWiFiData.put(ind + 1, (double) Math.round(100 * wiFiData.get(s) / maxValue));
        //            }
        //        }
        for (String s : wiFiData.keySet()) {
            int ind = nameIndex.indexOf(s);
            if (ind >= 0) {
                indexedWiFiData.put(ind + 1, wiFiData.get(s));
            }
        }
        List<FeatureNode> featureNodes = new ArrayList<FeatureNode>();
        TreeMap<Integer, Double> sortedWiFiData = new TreeMap<Integer, Double>(new Comparator<Integer>() {
            public int compare(Integer key1, Integer key2) {
                return key1 - key2;
            }
        });
        sortedWiFiData.putAll(indexedWiFiData);
        for (int i : sortedWiFiData.keySet()) {
            featureNodes.add(new FeatureNode(i, sortedWiFiData.get(i)));
        }
        Feature[] featureArray = new Feature[featureNodes.size()];
        for (int k = 0; k < featureNodes.size(); k++) {
            featureArray[k] = (Feature) featureNodes.get(k);
        }
        return featureArray;
    }


    static BufferedReader wifiListReader = null;
    static String[] names = null;
    static List<String> nameList = null;

    private static List<String> getNameList() throws IOException {
        //        if (wifiListReader == null) {
        //            wifiListReader = new BufferedReader(new InputStreamReader(context.getAssets().open(relation_name)));
        //            String line = wifiListReader.readLine();
        //            names = line.split(",");
        //            wifiListReader.close();
        //            nameList = new ArrayList<>();
        //            Collections.addAll(nameList, names);
        //        }
        return nameList;
    }
}
